#include "../head.h"

// 条件变量一般配合互斥锁一起使用,条件变量(队列):在线程不满足某一条件/情况的时候,将线程存放进条件变量中等待
// 作用于线程中

pthread_mutex_t mutex;
pthread_cond_t cond;
int money = 2000;
void *routine1(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("线程1加入条件变量\n");
        pthread_cond_wait(&cond, &mutex);
    }
    money -= 1000;
    printf("routine1 拿到钱了，当前银行卡余额:%d\n", money);

    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出 --走人
    pthread_exit(NULL);
}
void *routine2(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("线程2加入条件变量\n");
        pthread_cond_wait(&cond, &mutex);
    }
    money -= 1000;
    printf("routine2 拿到钱了，当前银行卡余额:%d\n", money);

    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出 --走人
    pthread_exit(NULL);
}
void *routine3(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("线程3加入条件变量\n");
        pthread_cond_wait(&cond, &mutex);
    }
    money -= 1000;
    printf("routine3 拿到钱了，当前银行卡余额:%d\n", money);

    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出 --走人
    pthread_exit(NULL);
}
void *routine4(void *arg)
{
    pthread_mutex_lock(&mutex); // 上锁

    // 条件不满足的时候进入条件变量中等待
    while (money < 1000)
    {
        printf("线程4加入条件变量\n");
        pthread_cond_wait(&cond, &mutex);
    }
    money -= 1000;
    printf("routine4 拿到钱了，当前银行卡余额:%d\n", money);

    pthread_mutex_unlock(&mutex); // 解锁

    // 主动退出 --走人
    pthread_exit(NULL);
}


int main()
{
    // 初始化条件变量
    pthread_cond_init(&cond, NULL);
    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);

    pthread_t thread1;
    pthread_t thread2;
    pthread_t thread3;
    pthread_t thread4;
    pthread_create(&thread1, NULL, routine1, NULL);
    pthread_create(&thread2, NULL, routine2, NULL);
    pthread_create(&thread3, NULL, routine3, NULL);
    pthread_create(&thread4, NULL, routine4, NULL);

    //==================================================================
    for (int i = 0; i < 5; i++)
    {
        printf("第一次  当前延时%ds\n",i);
        sleep(1);
    }
    pthread_mutex_lock(&mutex);
    money += 3000;
    printf("银行存钱成功，当前银行卡余额:%d\n", money);
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cond);
    //==================================================================
    sleep(5);
    // for (int i = 0; i < 5; i++)
    // {
    //     printf("第二次   当前延时%ds\n",i);
    //     sleep(1);
    // }
    // pthread_mutex_lock(&mutex);
    // money += 1000;
    // printf("银行存钱成功，当前银行卡余额:%d\n", money);
    // pthread_mutex_unlock(&mutex);
    // pthread_cond_broadcast(&cond);
    //==================================================================
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    pthread_join(thread4, NULL);

    // 销毁条件变量
    pthread_cond_destroy(&cond);
    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);

    return 0;
}


/*
    pthread_cond_t cond;
    pthread_cond_init(&cond, NULL);
    等价于 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
*/ 
/*
    // 阻塞等待一个条件变量 int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);
    // 限时等待一个条件变量 int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
*/